﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Serialization;
using SharePoint.Security.ContentScanner.Client.ViewModels;
using SharePoint.Security.ContentScanner.Engine.Analyzers;
using SharePoint.Security.ContentScanner.Engine.Helpers;
using SharePoint.Security.DocHelpers.ExportFormats;
using Hyperlink = System.Windows.Documents.Hyperlink;
using Path = System.IO.Path;

namespace SharePoint.Security.ContentScanner.Client
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Variables

        private List<string> urls = new List<string>();
        private List<Pattern> regexs = new List<Pattern>();
        private List<SelectedFileExtension> fileExtensions = new List<SelectedFileExtension>();
        private string _siteUrl = string.Empty;
        private string _type = string.Empty;
        private int _prerecoveryscannedsites = 0;
        private int _prerecoveryseelctedsites = 0;
        private List<ErrorInfo> _prerecoveryErrors = new List<ErrorInfo>();
        MainViewModel viewModel;
        protected string UserName = string.Empty;
        protected string Password = string.Empty;
        protected bool RecoveryModeUserCredentials = false;         

        #endregion

        #region Constructor

        public MainWindow()
        {
            //if (DateTime.Now > File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location).AddDays(10))
            //{
            //    MessageBox.Show("This copy of tool is expired. Please get a new copy of the tool.", "Sharepoint Content Scanner - Expired", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            //    Environment.Exit(1);
            //}
            InitializeComponent();
            viewModel = new MainViewModel();
            viewModel.GetData();
            ListRegEx.ItemsSource = viewModel.RegExes;
            ComboFileExtension.ItemsSource = viewModel.FileExtensions;
            ExpanderDeploymentType.IsExpanded = true;
            RdUrlFromTxt.IsChecked = true;
            viewModel.IsRecovery = false;
            if (!Directory.Exists(Directory.GetCurrentDirectory() + "\\ScanFiles"))
            {
                Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\ScanFiles");
            }
            RecoverPreviousScan();
        }

        #endregion

        #region Events
        private void ButtonClickScan(object sender, RoutedEventArgs e)
        {
            var logger = Logger.Log;
            string excelFileName = null;
            ExcelHelper excelHelp = new ExcelHelper();

            try
            {
                logger.Info(string.Format("------------------------------ Scan Started On : {0} ------------------------------", DateTime.Now.ToString()));
                logger.Info(string.Format("Temp Folder Path: {0}", Path.GetTempPath()));

                urls.Clear();
                regexs.Clear();
                fileExtensions.Clear();
                Helper.scanSummary.Clear();                
                this.GDResults.ItemsSource = null;
                this.GDResults.Items.Refresh();
                this.GDScanPatter.ItemsSource = null;
                this.GDScanPatter.Items.Refresh();
                this.GDErrors.ItemsSource = null;
                this.GDErrors.Items.Refresh();
                ((TabItem)this.ScanResultsTab.Items[1]).Header = "Errors";

                if (_type == string.Empty)
                {
                    _type = CboType.SelectedValue.ToString();
                }

                if (!viewModel.IsRecovery)
                {
                    //Create excel file to write scan results
                    excelFileName = string.Format("ScanResult-{0:yyyy-MM-dd_hh-mm-ss-tt}.xlsx", DateTime.Now);
                    viewModel.ExcelFileName = string.Format("{0}\\{1}", Directory.GetCurrentDirectory() + "\\ScanFiles", excelFileName);
                    excelHelp.CreateScanExcelFile(viewModel.ExcelFileName);
                    _prerecoveryscannedsites = 0;
                    _prerecoveryseelctedsites = 0;
                    _prerecoveryErrors.Clear();
                    viewModel.PreviousSelectedSites = 0;
                    viewModel.PreviousScannedSites = 0;
                    Helper.scanPatternSummary.Clear();
                    //SaveTreeView(Helper.ScanSitesView);
                    if (File.Exists(@"ScanFiles\PatternSummary.txt"))
                    {
                        File.Delete(@"ScanFiles\PatternSummary.txt");
                    }
                }

                SaveTreeView(Helper.scanSitesView);

                //Create text files for recovery logic
                if (File.Exists(@"ScanFiles\ToBeScannedSitesList.txt"))
                {
                    File.Delete(@"ScanFiles\ToBeScannedSitesList.txt");
                }


                if (RecoveryModeUserCredentials)
                {
                    if (ReadUserCredential()) return;

                    RecoveryModeUserCredentials = false;
                    BtnGetSites.Visibility = Visibility.Visible;
                }

                SaveScanSettings(this.mainTree.Items.Count, 0);

                foreach (SiteViewModel site in mainTree.Items)
                {
                    if (viewModel.IsRecovery)                        
                    {
                        List<SiteViewModel> newList = new List<SiteViewModel>();
                        foreach (SiteViewModel siteItem in mainTree.Items)
                        {
                            newList.Add(siteItem);
                        }
                        GetUserSelectedUrls(newList);                    
                    }
                    else
                    {
                        GetUserSelectedUrls(site.Subsites);
                    }
                }

                if (!File.Exists(@"ScanFiles\SitesScannedSummary.txt"))
                {
                    File.AppendAllText(@"ScanFiles\SitesScannedSummary.txt", (_prerecoveryscannedsites).ToString() + "," + "No. of sites scanned" + Environment.NewLine);
                    File.AppendAllText(@"ScanFiles\SitesScannedSummary.txt", viewModel.IsRecovery ? (_prerecoveryseelctedsites).ToString() : urls.Count.ToString() + "," + "No. of sites selected for scan" + Environment.NewLine);
                }
                if (!File.Exists(@"ScanFiles\PatternSummary.txt"))
                {
                    foreach (SummaryInfo sInfo in Helper.scanPatternSummary)
                    {
                        File.AppendAllText(@"ScanFiles\PatternSummary.txt", sInfo.Value.ToString() + "," + sInfo.Key.ToString() + Environment.NewLine);
                    }
                    //foreach (string pattern in File.ReadAllLines(@"Tracker\" + Helper.CurrentGuid + @"\PatternSummary.txt"))
                    //{
                    //    string[] patternResult = pattern.Split(",".ToCharArray(), 2);
                    //    Helper.ScanPatternSummary.Add(new SummaryInfo() { Key = patternResult[1], Value = patternResult[0] });
                    //}

                }

                if (!File.Exists(@"ScanFiles\ErrorSummary.txt"))
                {
                    foreach (ErrorInfo errorInfo in _prerecoveryErrors)
                    {
                        File.AppendAllText(@"ScanFiles\ErrorSummary.txt", errorInfo.Message + Environment.NewLine);
                    }
                    //foreach (string errorMsg in File.ReadAllLines(@"Tracker\" + Helper.CurrentGuid + @"\ErrorSummary.txt"))
                    //{
                    //    _prerecoveryErrors.Add(new ErrorInfo(errorMsg));
                    //}
                }

                Helper.scanSummary.Add(new SummaryInfo() {Key = "Excel File Name", Value = viewModel.ExcelFileName });                
                Helper.scanSummary.Add(new SummaryInfo() {Key = "No. of Sites selected for Scan", Value = (urls.Count + _prerecoveryscannedsites).ToString()});  
                viewModel.TotalSitesSelectedForScan = (urls.Count + _prerecoveryscannedsites);

                foreach (var item in this.ListRegEx.Items)
                {
                    var regex = item as RegExViewModel;

                    if (regex != null && regex.IsSelected)
                    {
                        regexs.Add(new Pattern
                                       {
                                           Name = regex.Name,
                                           RegEx = regex.Pattern
                                       });
                    }
                }

                if (!string.IsNullOrEmpty(TxtRegEx.Text.Trim()))
                {
                    regexs.Add(
                        new Pattern
                                       {
                                           Name = "Custom",
                                           RegEx = TxtRegEx.Text.Trim()
                                       }
                        );
                }

                foreach (var item in this.ComboFileExtension.Items)
                {
                    var fileExtn = item as FileExtensionViewModel;

                    if (fileExtn != null && fileExtn.IsSelected)
                    {
                        fileExtensions.Add(new SelectedFileExtension
                        {
                            FileExtension = fileExtn.FileExtension
                        });
                    }
                }

                if (regexs.Count == 0)
                {
                    MessageBox.Show("Please select regular expressions to scan.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                if (urls.Count == 0)
                {
                    MessageBox.Show("Please select URLs to scan.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                if (fileExtensions.Count == 0)
                {
                    MessageBox.Show("Please select File Extensions to scan.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                this._siteUrl = this.TxtUrl.Text;

                if (_type == "Online" && viewModel.IsRecovery)
                {
                    Helper.GetClientContext(urls.First(), _type);
                }

                var worker1 = new BackgroundWorker();
                worker1.DoWork += (o, ea) =>
                {
                    viewModel.Errors.Clear();
                    viewModel.Scan(urls, regexs, fileExtensions, _type);

                    //use the Dispatcher to delegate the listOfStrings collection back to the UI
                    Dispatcher.Invoke(
                        (Action)(() =>
                                     {
                                         try
                                         {
                                             Helper.scanSummary.Add(new SummaryInfo() {Key = "No. of sites scanned", Value = (viewModel.SuccessfullyScannedCount + _prerecoveryscannedsites).ToString()});

                                             this.GDErrors.ItemsSource = null;
                                             this.GDResults.ItemsSource = null;
                                             this.GDScanPatter.ItemsSource = null;
                                             this.GDResults.ItemsSource = Helper.scanSummary;
                                             this.GDScanPatter.ItemsSource = Helper.scanPatternSummary;
                                             this.GDErrors.Items.Clear();
                                             if (_prerecoveryErrors.Count > 0)
                                             {
                                                 viewModel.Errors.AddRange(_prerecoveryErrors);
                                             }
                                             this.GDErrors.ItemsSource = viewModel.Errors;

                                             ((TabItem)this.ScanResultsTab.Items[1]).Header = string.Format(
                                                 "Errors ({0})", viewModel.Errors.Count);                                            
                                             

                                             excelHelp.AddSummary(viewModel.ExcelFileName, Helper.scanSummary);
                                             excelHelp.AddPatternSummary(viewModel.ExcelFileName, Helper.scanPatternSummary);

                                             if (File.Exists(@"ScanFiles\ToBeScannedSitesList.txt"))
                                             {
                                                 File.Delete(@"ScanFiles\ToBeScannedSitesList.txt");
                                             }
                                             if (File.Exists(@"ScanFiles\SuccessfullyScannedSitesList.txt"))
                                             {
                                                 File.Delete(@"ScanFiles\SuccessfullyScannedSitesList.txt");
                                             }
                                             if (File.Exists(@"ScanFiles\ScanSettings.txt"))
                                             {
                                                 File.Delete(@"ScanFiles\ScanSettings.txt");
                                             }
                                             if (File.Exists(@"ScanFiles\PatternSummary.txt"))
                                             {
                                                 File.Delete(@"ScanFiles\PatternSummary.txt");
                                             }
                                             if (File.Exists(@"ScanFiles\ScanSiteView.xml"))
                                             {
                                                 File.Delete(@"ScanFiles\ScanSiteView.xml");
                                             }
                                             if (File.Exists(@"ScanFiles\SitesScannedSummary.txt"))
                                             {
                                                 File.Delete(@"ScanFiles\SitesScannedSummary.txt");
                                             }
                                             if (File.Exists(@"ScanFiles\ErrorSummary.txt"))
                                             {
                                                 File.Delete(@"ScanFiles\ErrorSummary.txt");
                                             }
                                         }
                                         catch (Exception ex)
                                         {
                                             MessageBox.Show(ex.Message);
                                         }

                                     })
                        );
                };
                worker1.RunWorkerCompleted += (o, ea) =>
                {

                    ProgressIndicator.IsBusy = false;
                    logger.Info(string.Format("------------------------------ Scan Completed On : {0} ------------------------------", DateTime.Now.ToString()));

                     
                    //Show button in UI to open generated file
                    DisplayExcelFileDetails(viewModel.ExcelFileName);

                };
                ProgressIndicator.IsBusy = true;
                ProgressIndicator.BusyContent = "Scanning site content. Please wait...";
                worker1.RunWorkerAsync();
                
            }
            catch (Exception ex)
            {
                var errorId = string.Format(new CultureInfo("en-US", false), "[UI Correlation Id : {0}]", Guid.NewGuid());
                var errorMsg = string.Format(new CultureInfo("en-US", false), "\n\nError: An unexpected error occurred while fetching the data. {0}", errorId);
                logger.Error(errorMsg, ex);
                string displayMsg = string.Format(new CultureInfo("en-US", false), "An unexpected error occurred while scanning for the content. Please refer error log for {0}", errorId);
                MessageBox.Show(displayMsg, "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void GetUserSelectedUrls(IEnumerable<SiteViewModel> siteCollection)
        {
            foreach (SiteViewModel site in siteCollection)
            {
                //if (site.IsSelected && !urls.Contains(site.SitePath.ToLower()) && !(site.SitePath.Equals("Sites to Scan")))
                if (site.IsSelected && !urls.Contains(site.SitePath, StringComparer.OrdinalIgnoreCase) && !(site.SitePath.Equals("Sites to Scan")))
                {
                    urls.Add(site.SitePath);
                    // writing urls to the file for recovery logic
                    File.AppendAllText(@"ScanFiles\ToBeScannedSitesList.txt", site.SitePath + Environment.NewLine);
                }

                GetUserSelectedUrls(site.Subsites);
            }
        }

        private void BtnGetSitesClick1(object sender, RoutedEventArgs e)
        {
           
            if (RdUrlFromFile.IsChecked == true)
            {
                var filePath = this.TxtUrlFromFile.Text.Trim();
                var siteUrls = new List<string>();

                if (string.IsNullOrEmpty(filePath))
                {
                    MessageBox.Show("Please provide file path containing site collection URLs.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                string[] lines = File.ReadAllLines(filePath);

                foreach (string urlString in lines)
                {
                    if (string.IsNullOrEmpty(urlString))
                        continue;

                    siteUrls.Add(urlString);
                }


                if (siteUrls.Count == 0)
                {
                    MessageBox.Show("Please provide file containing site collection URLs.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                ProcessUrls(siteUrls);
            }
            else if (RdUrlFromTxt.IsChecked == true)
            {
                var siteUrlFromTxt = this.TxtUrl.Text.Trim();

                if (string.IsNullOrEmpty(siteUrlFromTxt))
                {
                    MessageBox.Show("Please provide site collection URL.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;   
                }
                var siteUrls = new List<string>
                               {
                                   this.TxtUrl.Text
                               };
                ProcessUrls(siteUrls);
            }

        }

        private void ProcessUrls(List<string> siteUrls )
        {
            Helper.userName = string.Empty;
            Helper.userDomain = string.Empty;
            Helper.password = string.Empty;
            viewModel.IsRecovery = false;

            if (mainTree.Items.Count > 0)
            {
                mainTree.ItemsSource = null;
                mainTree.Items.Refresh();
            }

            var logger = Logger.Log;
            try
            {
                //Clear the UI grids with data if previous run data is present
                Helper.scanSitesView.Subsites.Clear();
                Helper.scanSitesView.IsSelected = true;
                Helper.scanSitesView.IsUserEnabled = true;

                if (this.GDResults.Items.Count > 0)
                {
                    this.GDResults.ItemsSource = null;
                    this.GDResults.Items.Refresh();
                    this.GDScanPatter.ItemsSource = null;
                    this.GDScanPatter.Items.Refresh();
                    this.GDErrors.ItemsSource = null;
                    this.GDErrors.Items.Refresh();
                    ((TabItem) this.ScanResultsTab.Items[1]).Header = "Errors";
                }


                bool fetcSubSites = this.ChkProcessSubSites.IsChecked == true;

                if (siteUrls == null || siteUrls.Count == 0)
                {
                    MessageBox.Show("Please provide site collection URL.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                _type = CboType.SelectedValue.ToString();
                if (_type == "Online")
                {
                    ProgressIndicator.IsBusy = true;
                    ProgressIndicator.BusyContent = "Fetching sites for provided URIs. Please wait...";
                    viewModel.GetSites(siteUrls, _type, fetcSubSites);
                    ProgressIndicator.IsBusy = false;

                    DisplayTree();

                    if (viewModel.Errors.Count > 0)
                    {
                        var msg = string.Empty;
                        foreach (var errorInfo in viewModel.Errors)
                        {
                            msg = errorInfo.Message + Environment.NewLine;
                        }
                        MessageBox.Show(msg, "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                else
                {
                    if (ReadUserCredential()) return;

                    var worker = new BackgroundWorker();
                    worker.DoWork += (o, ea) =>
                    {
                        viewModel.GetSites(siteUrls, _type, fetcSubSites);

                        //use the Dispatcher to delegate the listOfStrings collection back to the UI
                        Dispatcher.Invoke((Action) (() =>
                        {

                            DisplayTree();

                            if (viewModel.Errors.Count > 0)
                            {
                                var msg = string.Empty;
                                foreach (var errorInfo in viewModel.Errors)
                                {
                                    msg += errorInfo.Message + Environment.NewLine;
                                }
                                TxtPassword.Password = string.Empty;
                                mainTree.ItemsSource = null;
                                mainTree.Items.Refresh();
                                MessageBox.Show(msg, "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                            }

                        }));
                    };
                    worker.RunWorkerCompleted += (o, ea) =>
                    {
                        ProgressIndicator.IsBusy = false;
                    };
                    ProgressIndicator.IsBusy = true;
                    ProgressIndicator.BusyContent = "Connecting to site collection. Please wait...";

                    worker.RunWorkerAsync();
                    ProgressIndicator.IsBusy = true;
                    //ListSites.ItemsSource = viewModel.Sites;
                    //DisplayTree();
                }
            }
            catch (IndexOutOfRangeException)
            {
                TxtUserName.Text = string.Empty;
                TxtPassword.Password = string.Empty;
                MessageBox.Show(
                    @"Username provided is not in correct format. Please provide Domain\Username details again.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error); ;
            }
            catch (ArgumentException agex)
            {
                MessageBox.Show("An application error has occured: " + agex.Message, "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                if(ProgressIndicator.IsBusy) ProgressIndicator.IsBusy = false;
            }
            catch (ApplicationException aex)
            {
                MessageBox.Show("An application error occurred while fetching data. " + aex.Message, "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                if (ProgressIndicator.IsBusy) ProgressIndicator.IsBusy = false;
            }
            catch (UriFormatException uex)
            {
                MessageBox.Show("An application error has occured: " + uex.Message, "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                if (ProgressIndicator.IsBusy) ProgressIndicator.IsBusy = false;
            }
            catch (NullReferenceException)
            {
                MessageBox.Show("An application error has occured. Please check the URI provided", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                if (ProgressIndicator.IsBusy) ProgressIndicator.IsBusy = false;
            }
            //catch (System.Net.WebException webex)
            //{
            //    MessageBox.Show("An application error has occured while fetching data: Requested site/s returned unauthorized error", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
            //    return;
            //}
            catch (Exception ex)
            {
                TxtPassword.Password = string.Empty;
                mainTree.ItemsSource = null;
                if (ProgressIndicator.IsBusy) ProgressIndicator.IsBusy = false;
                var errorId = string.Format(new CultureInfo("en-US", false), "[UI Correlation Id : {0}]", Guid.NewGuid());
                var errorMsg = string.Format(new CultureInfo("en-US", false), "\n\nError: An unexpected error occurred while fetching the data. {0}", errorId);
                logger.Error(errorMsg, ex);
                string displayMsg = string.Format(new CultureInfo("en-US", false), "An unexpected error occurred while scanning for the content. Please refer error log for {0}", errorId);
                MessageBox.Show(displayMsg, "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private bool ReadUserCredential()
        {
            if (chkUserCredentials.IsChecked == true)
            {
                //Check for user credentials
                string uName = string.Empty;
                string uDomain = string.Empty;
                string pwd = string.Empty;

                if (TxtUserName.Text != string.Empty)
                {
                    String[] nameParts = TxtUserName.Text.Split('\\');
                    uName = nameParts[1];
                    uDomain = nameParts[0];
                }
                else
                {
                    MessageBox.Show(@"Please provide Username (Domain\Username)", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return true;
                }

                if (TxtPassword.Password != string.Empty)
                {
                    pwd = TxtPassword.Password;
                }
                else
                {
                    MessageBox.Show("Please provide Password", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return true;
                }

                if (uName != string.Empty && pwd != null && uDomain != string.Empty)
                {
                    Helper.userName = uName;
                    Helper.password = pwd;
                    Helper.userDomain = uDomain;
                }
                else
                {
                    TxtUserName.Text = string.Empty;
                    TxtPassword.Password = string.Empty;
                    MessageBox.Show(@"Username (Domain\Username) or Password is not in correct format. Please reenter.", "Sharepoint Content Scanner - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return true;
                }
            }
            return false;
        }

        private void DisplayTree()
        {
            if (Helper.scanSitesView.Subsites.Count > 0)
            {
                List<SiteViewModel> tree = new List<SiteViewModel>();
                tree.Add(Helper.scanSitesView);
                mainTree.ItemsSource = tree;
            }
        }

        private void SaveTreeView(SiteViewModel mainTreeNode)
        {
            if (File.Exists(@"ScanFiles\ScanSiteView.xml"))
            {
                File.Delete(@"ScanFiles\ScanSiteView.xml");
            }  
            using (var writer = new StreamWriter(@"ScanFiles\ScanSiteView.xml"))
            {
                var serializer = new XmlSerializer(typeof(SiteViewModel));
                serializer.Serialize(writer, mainTreeNode);
                writer.Flush();
            }
        }

        private void DisplayExcelFileDetails(string excelFileName)
        {
            try
            {
                //var exportedFilePath = Export();
                Clipboard.SetText(excelFileName);

                if (MessageBox.Show(string.Format("File is saved at {0}. Path is also copied to clipboard. " +"{1}{1}Would you like to view result data now?", excelFileName,Environment.NewLine), "Save Results", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.Yes)
                {
                    ProgressIndicator.IsBusy = true;
                    ProgressIndicator.BusyContent = "Generating excel file. Please wait...";
                    Process.Start(excelFileName);
                    ProgressIndicator.IsBusy = false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(
                    "An error occured during the operation. Please try again.{0}Error: {1}", Environment.NewLine,
                    ex.Message)
                    , "Save File - Error", MessageBoxButton.OK, MessageBoxImage.Error);
                throw;
            }
        }

        private void DgHyperlinkClick(object sender, RoutedEventArgs e)
        {
            var link = (Hyperlink)e.OriginalSource;
            Process.Start(link.NavigateUri.AbsoluteUri);
        }

        private void Expander_OnExpanded(object sender, RoutedEventArgs e)
        {
            var expander = e.Source as Expander;
            if (expander != null) ControlExpanderVisibility(expander.Name);
        }

        private void ControlExpanderVisibility(string controlName)
        {
            ExpanderDeploymentType.IsExpanded = "ExpanderDeploymentType" == controlName;
            ExpanderFileExt.IsExpanded = "ExpanderFileExt" == controlName;
            ExpanderRegEx.IsExpanded = "ExpanderRegEx" == controlName;
            ExpanderSiteCollection.IsExpanded = "ExpanderSiteCollection" == controlName;
        }

        private void BtnBrowse_OnClick(object sender, RoutedEventArgs e)
        {
            // Create OpenFileDialog 

            var dlg = new Microsoft.Win32.OpenFileDialog
            {
                DefaultExt = ".txt",
                Filter = "Text documents (.txt)|*.txt"
            };



            // Set filter for file extension and default file extension 


            // Display OpenFileDialog by calling ShowDialog method 

            bool? result = dlg.ShowDialog();



            // Get the selected file name and display in a TextBox 

            if (result == true)
            {

                // Open document 

                string filename = dlg.FileName;

                TxtUrlFromFile.Text = filename;

            }
        }

        private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
        {

            PanelUrlFromText.Visibility = RdUrlFromTxt.IsChecked == true ? Visibility.Visible : Visibility.Collapsed;
            PanelUrlFromFile.Visibility = RdUrlFromFile.IsChecked == true ? Visibility.Visible : Visibility.Collapsed; ;

        }

        #endregion

        #region Methods

        private void SaveScanSettings(int totalSitesCount, int successfulSitesCount)
        {
            System.Text.StringBuilder scanSettings = new System.Text.StringBuilder();
            scanSettings.AppendLine("Deployment Type :" + CboType.SelectedValue.ToString());
            scanSettings.AppendLine("URL Source :" + (RdUrlFromTxt.IsChecked == true ? "Text" : "File"));
            scanSettings.AppendLine("Site Collection URL/Text File Path :" + (RdUrlFromTxt.IsChecked == true ? TxtUrl.Text.Trim() : this.TxtUrlFromFile.Text.Trim()));
            scanSettings.AppendLine("Process Sub Sites :" + (ChkProcessSubSites.IsChecked == true ? true.ToString() : false.ToString()));
            foreach (var item in this.ListRegEx.Items)
            {
                var regex = item as RegExViewModel;
                if (regex != null && regex.IsSelected)
                {
                    scanSettings.AppendLine("RegEx :" + regex.Pattern + "-" + regex.Name);
                }
            }
            if (!string.IsNullOrEmpty(TxtRegEx.Text.Trim()))
            {
                scanSettings.AppendLine("RegEx :" + TxtRegEx.Text.Trim() + "-" + "Custom");
            }
            foreach (var item in this.ComboFileExtension.Items)
            {
                var fileExtn = item as FileExtensionViewModel;
                if (fileExtn != null && fileExtn.IsSelected)
                {
                    scanSettings.AppendLine("FileEx :" + fileExtn.FileExtension + "-" + fileExtn.Name);
                }
            }
            if (Helper.userName != string.Empty && Helper.userDomain != string.Empty && Helper.password != string.Empty)
            {
                scanSettings.AppendLine("User credentials provided :  True");
            }
            scanSettings.AppendLine("Total Sites Count :" + totalSitesCount);
            scanSettings.AppendLine("Successfully Scanned Sites Count :" + successfulSitesCount);
            scanSettings.AppendLine("Excel File Name :" + viewModel.ExcelFileName);

            if (File.Exists(@"ScanFiles\ScanSettings.txt"))
            {
                File.Delete(@"ScanFiles\ScanSettings.txt");
            }
            File.AppendAllText(@"ScanFiles\ScanSettings.txt", scanSettings.ToString());
        }

        private void RecoverPreviousScan()
        {
            List<string> scanFailedSites = new List<string>();
            if (File.Exists(@"ScanFiles\ToBeScannedSitesList.txt") && File.Exists(@"ScanFiles\SuccessfullyScannedSitesList.txt"))
            {
                var file1Content = File.ReadAllLines(@"ScanFiles\ToBeScannedSitesList.txt");
                var file2Content = File.ReadAllLines(@"ScanFiles\SuccessfullyScannedSitesList.txt");
                scanFailedSites = file1Content.Except(file2Content).ToList<string>();
                //_prerecoveryscannedsites = file2Content.Count();
                File.Delete(@"ScanFiles\ToBeScannedSitesList.txt");
                File.Delete(@"ScanFiles\SuccessfullyScannedSitesList.txt");
            }
            else if (File.Exists(@"ScanFiles\ToBeScannedSitesList.txt"))
            {
                scanFailedSites = File.ReadAllLines(@"ScanFiles\ToBeScannedSitesList.txt").ToList<string>();
                File.Delete(@"ScanFiles\ToBeScannedSitesList.txt");
            }    
            else
            {
                return;
            }
            
            if (scanFailedSites.Count > 0)
            {
                System.Text.StringBuilder summaryText = new System.Text.StringBuilder();
                BindingList<RegExViewModel> recoveryRegEx = new BindingList<RegExViewModel>();
                BindingList<FileExtensionViewModel> recoveryFileEx = new BindingList<FileExtensionViewModel>();
                string deploymentType = string.Empty;
                string urlSource = string.Empty;
                string urlFilePath = string.Empty;
                bool processSubSites = false;
                bool isRegExSet = false;
                bool isFileExSet = false;

                if (File.Exists(@"ScanFiles\SitesScannedSummary.txt"))
                {
                    var scannedData = File.ReadAllLines(@"ScanFiles\SitesScannedSummary.txt");
                    foreach (var line in scannedData)
                    {
                        string[] lineResult = line.Split(",".ToCharArray(), 2);
                        if (lineResult[1] == "No. of sites selected for scan")
                        {
                            int.TryParse(lineResult[0], out _prerecoveryseelctedsites); //read from file
                            viewModel.PreviousSelectedSites = _prerecoveryseelctedsites;
                        }
                        else if (lineResult[1] == "No. of sites scanned")
                        {
                            int.TryParse(lineResult[0], out _prerecoveryscannedsites); //read from text file
                            viewModel.PreviousScannedSites = _prerecoveryscannedsites;
                        }

                        File.Delete(@"ScanFiles\SitesScannedSummary.txt");
                    }
                }

                if (File.Exists(@"ScanFiles\ScanSettings.txt"))
                {
                    var scanSettings = File.ReadAllLines(@"ScanFiles\ScanSettings.txt");
                    int startingIndex = 0;                        

                    foreach(var setting in scanSettings)
                    {
                        startingIndex = setting.IndexOf(":");

                        if (setting.StartsWith("Deployment Type :"))
                        {
                            deploymentType = setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1);
                            summaryText.AppendLine("Deployment Type : " + deploymentType);                                
                        }
                        else if (setting.StartsWith("URL Source :"))
                        {
                            urlSource = setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1);
                            summaryText.AppendLine("URL Source : " + urlSource);
                        }
                        else if (setting.StartsWith("Site Collection URL/Text File Path :"))
                        {
                            urlFilePath = setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1);
                            summaryText.AppendLine("Site Collection URL/Text File Path : " + urlFilePath);
                        }
                        else if (setting.StartsWith("Process Sub Sites :"))
                        {
                            processSubSites = Convert.ToBoolean(setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1));
                            summaryText.AppendLine("Process Sub Sites : " + processSubSites.ToString());
                        }
                        else if (setting.StartsWith("RegEx :"))
                        {
                            if (!isRegExSet)
                            {
                                summaryText.AppendLine("Selected Regular Extensions : ");
                                isRegExSet = true;
                            }
                            string regExValue = setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1);
                            int regExLastIndex = regExValue.LastIndexOf("-");
                            summaryText.AppendLine(regExValue);

                            RegExViewModel regExPattern = new RegExViewModel();
                            regExPattern.Pattern = regExValue.Substring(0, regExLastIndex);
                            regExPattern.Name = regExValue.Substring(regExLastIndex + 1, regExValue.Length - regExLastIndex - 1);
                            regExPattern.IsSelected = true;
                            recoveryRegEx.Add(regExPattern);
                        }
                        else if (setting.StartsWith("FileEx :"))
                        {
                            if (!isFileExSet)
                            {
                                summaryText.AppendLine("Selected File Extensions : ");
                                isFileExSet = true;
                            }                                
                            string fileExValue = setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1);
                            int fileExLastIndex = fileExValue.LastIndexOf("-");
                            summaryText.AppendLine(fileExValue);

                            FileExtensionViewModel fileExPattern = new FileExtensionViewModel();
                            fileExPattern.FileExtension = fileExValue.Substring(0, fileExLastIndex);
                            fileExPattern.Name = fileExValue.Substring(fileExLastIndex + 1, fileExValue.Length - fileExLastIndex - 1);
                            fileExPattern.IsSelected = true;
                            recoveryFileEx.Add(fileExPattern);                                
                        }
                        else if (setting.StartsWith("User credentials provided :"))
                        {
                            summaryText.AppendLine("User provided credentials for connecting to the scan sites");
                            RecoveryModeUserCredentials = true;
                        }
                        else if(setting.StartsWith("Total Sites Count :"))
                        {
                            //summaryText.AppendLine("Scan Initiated Sites Count : " + setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1));
                            summaryText.AppendLine("Scan Initiated Sites Count : " + (_prerecoveryseelctedsites).ToString());
                        }
                        else if(setting.StartsWith("Successfully Scanned Sites Count :"))
                        {
                            //summaryText.AppendLine("Successfully Scanned Sites Count : " + setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1));
                            summaryText.AppendLine("Successfully Scanned Sites Count : " + _prerecoveryscannedsites.ToString());
                        }
                        else if (setting.StartsWith("Excel File Name :"))
                        {
                            viewModel.ExcelFileName = setting.Substring(startingIndex + 1, setting.Length - startingIndex - 1);
                        }
                    }
                }

                string msgSummary = "Content Scanner found a failed scan. Here is the summary of the settings and other details." + Environment.NewLine + Environment.NewLine + summaryText + Environment.NewLine + "Would you like to re-scan the failed sites.";
                MessageBoxResult reScanResult = MessageBox.Show(msgSummary, "Failed Scan Summary", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
                if (reScanResult == MessageBoxResult.Yes)
                {
                    viewModel.IsRecovery = true;
                    ProgressIndicator.IsBusy = true;
                    ProgressIndicator.BusyContent = "Fetching the scan failed sites to re-scan...";
                    List<SiteViewModel> failedSites = new List<SiteViewModel>();
                    foreach (var site in scanFailedSites)
                    {
                        SiteViewModel svm = new SiteViewModel();
                        svm.IsSelected = true;
                        svm.SitePath = site;
                        failedSites.Add(svm);
                    }

                    List<SiteViewModel> siteModel = new List<SiteViewModel>();
                    using (var stream = System.IO.File.OpenRead(@"ScanFiles\ScanSiteView.xml"))
                    {
                        var serializer = new XmlSerializer(typeof (SiteViewModel));
                        siteModel.Add((SiteViewModel) serializer.Deserialize(stream));
                    }

                    Helper.scanSitesView = siteModel[0];
                    mainTree.ItemsSource = BuildTreeForRecoverySites(siteModel, scanFailedSites);                 

                    foreach (var regExSetting in viewModel.RegExes)
                    {
                        regExSetting.IsSelected = false;
                        foreach (var recoveryRegExSetting in recoveryRegEx)
                        {
                            if (regExSetting.Pattern == recoveryRegExSetting.Pattern &&
                                regExSetting.Name == recoveryRegExSetting.Name)
                            {
                                regExSetting.IsSelected = true;
                            }
                            if (recoveryRegExSetting.Name.ToLower() == "custom")
                            {
                                TxtRegEx.Text = recoveryRegExSetting.Pattern;
                            }
                        }
                    }

                    foreach (var fileExSetting in viewModel.FileExtensions)
                    {
                        fileExSetting.IsSelected = false;
                        foreach (var recoveryFileExSetting in recoveryFileEx)
                        {
                            if (fileExSetting.FileExtension == recoveryFileExSetting.FileExtension &&
                                fileExSetting.Name == recoveryFileExSetting.Name)
                            {
                                fileExSetting.IsSelected = true;
                            }
                        }
                    }

                    CboType.SelectedValue = deploymentType;

                    //Read pattern count for previous scan
                    if (File.Exists(@"ScanFiles\PatternSummary.txt"))
                    {
                        foreach (string pattern in File.ReadAllLines(@"ScanFiles\PatternSummary.txt"))
                        {
                            string[] patternResult = pattern.Split(",".ToCharArray(), 2);
                            Helper.scanPatternSummary.Add(new SummaryInfo() { Key = patternResult[1], Value = patternResult[0]});
                        }

                        File.Delete(@"ScanFiles\PatternSummary.txt");
                    }

                    if (File.Exists(@"ScanFiles\ErrorSummary.txt"))
                    {
                        foreach (string errorMsg in File.ReadAllLines(@"ScanFiles\ErrorSummary.txt"))
                        {
                            _prerecoveryErrors.Add(new ErrorInfo(errorMsg));                           
                        }
                    }

                    RdUrlFromFile.IsChecked = false;
                    RdUrlFromTxt.IsChecked = false;
                    if (RecoveryModeUserCredentials)
                    {
                        chkUserCredentials.IsChecked = true;
                        BtnGetSites.Visibility = Visibility.Hidden;
                    }

                    ComboFileExtension.ItemsSource = viewModel.FileExtensions;
                    ControlExpanderVisibility("ExpanderSiteCollection");
                    ProgressIndicator.IsBusy = false;
                }
                else
                {
                    if (File.Exists(@"ScanFiles\PatternSummary.txt"))
                    {
                        File.Delete(@"ScanFiles\PatternSummary.txt");
                    }
                    if (File.Exists(@"ScanFiles\ScanSiteView.xml"))
                    {
                        File.Delete(@"ScanFiles\ScanSiteView.xml");
                    }
                    if (File.Exists(@"ScanFiles\ScanSettings.txt"))
                    {
                        File.Delete(@"ScanFiles\ScanSettings.txt");
                    }
                    if (File.Exists(@"ScanFiles\SitesScannedSummary.txt"))
                    {
                        File.Delete(@"ScanFiles\SitesScannedSummary.txt");
                    }
                    if (File.Exists(@"ScanFiles\ErrorSummary.txt"))
                    {
                        File.Delete(@"ScanFiles\ErrorSummary.txt");
                    }

                    _prerecoveryscannedsites = 0;
                    _prerecoveryseelctedsites = 0;
                    viewModel.PreviousSelectedSites = 0;
                    viewModel.PreviousScannedSites = 0;
                    _prerecoveryErrors.Clear();
                }
            }
        }

        private static IEnumerable<SiteViewModel> BuildTreeForRecoverySites(IEnumerable<SiteViewModel> siteModel, List<string> failedSites)
        {
            foreach (SiteViewModel site in siteModel)
            {
                if (!failedSites.Contains(site.SitePath, StringComparer.OrdinalIgnoreCase))
                {
                    site.IsSelected = false;
                    site.IsUserEnabled = false;
                }

                BuildTreeForRecoverySites(site.Subsites, failedSites);
            }

            return siteModel;
        }

        #endregion        
       

        private void chkUserCredentials_Unchecked(object sender, RoutedEventArgs e)
        {
            TxtUserName.Text = string.Empty;
            TxtPassword.Password = string.Empty;
            Helper.userName = string.Empty;
            Helper.password = string.Empty;
        }

        private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            string unselectedNode = ((CheckBox) sender).Content.ToString();

            SetDuplicateSiteState(unselectedNode.ToLower(), Helper.scanSitesView.Subsites, false);
        }

        private void SetDuplicateSiteState(string selectedSiteNode, CustomObservableCollection<SiteViewModel> subsiteCollection, bool checkState)
        {            
            foreach (SiteViewModel siteModel in subsiteCollection)
            {
                if (siteModel.SitePath.ToLower() == selectedSiteNode)
                {
                    siteModel.IsSelected = checkState;
                }

                SetDuplicateSiteState(selectedSiteNode, siteModel.Subsites, checkState);
            }
        }

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {
            string selectedNode = ((CheckBox)sender).Content.ToString();

            SetDuplicateSiteState(selectedNode.ToLower(), Helper.scanSitesView.Subsites, true);
        }
    }
}
